import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
import { ElMessage } from 'element-plus';
import { AjaxResponseWrapper, APP_TOKEN } from '~/common/index.ts';
import { useUserStore } from '~/store/modules/user.ts';

const request = axios.create({
  baseURL: import.meta.env.VITE_APP_BASE_URL,
  withCredentials: true,
  timeout: 1000 * 60 * 2
});

/**
 * 请求拦截
 */
request.interceptors.request.use(requestConfig => {
  // console.log('实例请求拦截器');
  requestConfig.headers[APP_TOKEN] = useUserStore().getToken();
  return requestConfig;
});

/**
 * 响应拦截
 */
request.interceptors.response.use(response => {
  return response;
});

/**
 * GET请求封装
 * @param url
 * @param params
 */
export const get = <D>(
  url: string,
  params?: Record<string, any>
): Promise<AjaxResponseWrapper<D>> => {
  return doRequest({
    method: 'GET',
    url,
    params
  });
};

/**
 * POST请求封装
 * @param url
 * @param data
 */
export const post = <D>(
  url: string,
  data?: Record<string, any>
): Promise<AjaxResponseWrapper<D>> => {
  return doRequest({
    method: 'POST',
    url,
    data,
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    }
  });
};

export const postByFormData = <D>(
  url: string,
  data?: Record<string, any>
): Promise<AjaxResponseWrapper<D>> => {
  return doRequest({
    method: 'POST',
    url,
    data,
    headers: {
      'Content-Type': 'multipart/form-data;charset=utf-8'
    }
  });
};

export const postByJSON = <D>(
  url: string,
  data?: Record<string, any>
): Promise<AjaxResponseWrapper<D>> => {
  return doRequest({
    method: 'POST',
    url,
    data
  });
};

const doRequest = <D>(config: AxiosRequestConfig): Promise<AjaxResponseWrapper<D>> => {
  let response = request.request<
    AjaxResponseWrapper<D>,
    AxiosResponse<AjaxResponseWrapper<D>>,
    any
  >(config);
  return handleResponse(response);
};

const handleResponse = <D>(
  response: Promise<AxiosResponse<AjaxResponseWrapper<D>>>
): Promise<AjaxResponseWrapper<D>> => {
  return new Promise((resolve, reject) => {
    response
      .then(res => {
        if (10015 === res.data.code || 10017 === res.data.code || 10018 === res.data.code) {
          useUserStore().logout();
        }
        resolve(res.data);
      })
      .catch(error => {
        ElMessage.error({
          message: error.message,
          offset: 50
        });
        reject({
          code: 10005,
          message: error.message
        });
      });
  });
};

export interface ResponseOptions {
  /**
   * ajax响应的数据
   */
  data: AjaxResponseWrapper<any>;

  /**
   * 请求成功回调
   */
  onSuccess?: () => void;

  /**
   * 请求失败回调
   */
  onFailure?: () => void;

  /**
   * 是否显示成功的消息
   */
  showSuccessMessage?: boolean;

  /**
   * 是否显示失败的消息
   */
  showErrorMessage?: boolean;
}

export const SUCCESS_CODE = 10000;

/**
 * 对ajax响应的统一处理
 * @param responseOptions
 */
export const parseAjaxResponse = (responseOptions: ResponseOptions) => {
  let {
    data,
    onSuccess,
    onFailure,
    showSuccessMessage = true,
    showErrorMessage = true
  } = responseOptions;
  if (data) {
    let message = data.message;
    if (data.code === SUCCESS_CODE) {
      onSuccess && onSuccess();

      if (showSuccessMessage && message) {
        ElMessage.success({
          message: data.message,
          offset: 50
        });
      }
    } else if (data.code === 20004) {
      // 橙色弹框
      if (data.message) {
        ElMessage.warning({
          message: data.message,
          offset: 50
        });
        onFailure && onFailure();
      }
    } else {
      if (showErrorMessage && message) {
        ElMessage({
          type: 'error',
          message: data.message,
          showClose: true,
          duration: 5000,
          grouping: true,
          offset: 50
        });
      }
      onFailure && onFailure();
    }
  } else {
    if (onFailure) {
      onFailure();
    } else {
      ElMessage({
        type: 'error',
        message: '服务器繁忙，请稍后重试',
        showClose: true,
        duration: 5000,
        grouping: true,
        offset: 50
      });
    }
  }
};
